/*
 * Licensed to Nanjing RedOrange Co. ltd (RedOrange) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * RedOrange licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package redora.generator;

import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import redora.generator.exceptions.ModelGenerationException;

import java.io.File;
import java.util.Collection;

/**
 * Generates persistence sources and resources. If any XML schema is located in the
 * xsd directory, also the JAXB sources will be generated.
 *
 * @author jaap
 * @goal generate
 * @phase generate-sources
 */
public class GenerateMojo extends AbstractMojo {

    /**
     * The basePackage is always suffixed by this value. This will make all the
     * projects using this library more easy to use because the persistence
     * classes are all to be found under basePackage.PACKAGE_SUFFIX.
     */
    public static final String PACKAGE_SUFFIX = "rdo";

    public static final String GENERATION_TARGET = "redora-target";

    /**
     * Location of the file.
     *
     * @parameter expression="${project.build.directory}"
     * @required
     */
    private File buildDir;

    /**
     * Package where the sources should be generated into.
     *
     * @parameter expression=${persistulate.baseParameter}
     * default="${project.groupId}.${project.artifactId}"
     * @required
     */
    private String basePackage;

    /**
     * @parameter expression="${project.artifactId}"
     * @required
     */
    private String artifactId;

    /**
     * Default language of the project.
     *
     * @parameter expression=${persistulate.baseParameter} default="en"
     * @required
     */
    private String defaultLanguage;

    /**
     * Default base project for generating directory of the project.
     * This is only used for this project itself (p-configuration).
     * So, for example when you run the generator in a main project, but you actually want it to generate
     * the sources in a sub project, you must use this.
     *
     * @parameter expression=${persistulate.baseParameter} default=""
     */
    private String baseProjectDir;

    /**
     * src/main/resources/model/xsd
     */
    private File schemaDirectory;

    public void execute() throws MojoExecutionException {
        //Setting the directories
        String sourceDir = "src" + File.separator + "main" + File.separator + "java";
        String resourceDir = "src" + File.separator + "main" + File.separator + "resources";
        String modelDir = resourceDir + File.separator + "model";
        if (baseProjectDir != null && new File(baseProjectDir).isDirectory()) {
            getLog().info("Prefixed " + baseProjectDir + " as root");
            sourceDir = baseProjectDir + File.separator + sourceDir;
            resourceDir = baseProjectDir + File.separator + resourceDir;
            modelDir = baseProjectDir + File.separator + modelDir;
        }
        schemaDirectory = new File(modelDir + File.separator + "xsd");

        String jaxbPackage = basePackage + "." + PACKAGE_SUFFIX + ".model.xml";
        File generateDirectory = new File(buildDir + File.separator + "generated-sources" + File.separator + GENERATION_TARGET);
        getLog().info("Generating sources for you now. I will use the following directories and settings");
        getLog().info("- Java source: " + sourceDir);
        getLog().info("- Generated java source " + generateDirectory.getPath());
        getLog().info("- Base package " + basePackage + "(." + PACKAGE_SUFFIX + ")");
        getLog().info("- XML Schemas location " + schemaDirectory.getPath());
        getLog().info("- JAXB package " + jaxbPackage);
        try {
            ModelProcessor.generate(
                    basePackage + "." + PACKAGE_SUFFIX
                    , defaultLanguage
                    , sourceDir
                    , buildDir.getPath()
                    , resourceDir
                    , artifactId
            );
            getLog().info("All model sources are generated");
            if (xml() != null && !xml().isEmpty()) {
                getLog().info("Found " + xml().size()
                        + " XML Schema(s), i will generate JAXB things for it (them)");
                JAXBGenerator jaxb = new JAXBGenerator(xml(), generateDirectory, jaxbPackage);
                jaxb.execute();
            } else {
                getLog().info("Did not find any XSD to generate");
            }
        } catch (ModelGenerationException e) {
            throw new MojoExecutionException(e.getMessage(), e);
        } catch (Exception e) {
            throw new MojoExecutionException("Ooops", e);
        }
    }

    /**
     * Get xsd file list from schemaDirectory.
     *
     * @return xml list
     */
    @SuppressWarnings("unchecked")
    private Collection<File> xml() {
        if (schemaDirectory.exists()) {
            return FileUtils.listFiles(schemaDirectory, new String[]{"xsd"}, false);
		}
		return null;
	}
}
